﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Wicture.DbRESTFul;
using Wicture.DbRESTFul.SQL;
using Wicture.EPC.Common;
using Wicture.EPC.Service.V1.Models;
using Wicture.EPC.Service.V1.Repository;

namespace Wicture.EPC.Service.V1.QueryInterceptors.Interceptors
{
    public class MitsubishiQueryInterceptor : BaseQueryInterceptor
    {
        private readonly string[] brandCodes = new string[] { "mitsubishi" };
        public override string[] BrandCodes => brandCodes;

        protected override List<Query_PartsResult> GetParts(DbRESTFulRepository repository, JObject param)
        {
            return repository.Invoke<Query_PartsResult>(CSIs.Query_Parts_For_Mitsubishi, param);
        }
        protected override dynamic QueryVinByCode(DbRESTFulRepository repository, Get_Model_InfoParam param)
        {
            object vinParam = null;
            if (string.IsNullOrEmpty(param.selectorId))
            {
                vinParam = new { param.vin };
            }
            else
            {
                vinParam = new { param.vin, param.selectorId };
            }
            return repository.Invoke(CSIs.Query_Vin_By_Code_For_Mitsubishi, vinParam);
        }
        protected override Get_Model_InfoResult BuildVinResult(dynamic vin)
        {
            if (vin == null)
            {
                throw new LogicalException($"未找到该Vin码(三菱)！", 610);
            }
            IEnumerable<dynamic> list = Enumerable.ToList(vin);
            if (list.Count() == 0)
            {
                throw new LogicalException($"未找到该Vin码(三菱)！", 610);
            }
            else if (list.Count() == 1)
            {
                return JObject.FromObject(list.First()).ToObject<Get_Model_InfoResult>();
            }
            else
            {
                Get_Model_InfoResult model = JObject.FromObject(list.First()).ToObject<Get_Model_InfoResult>();
                model.multiModel = new Get_Model_InfoResult._MultiModel
                {
                    title = "选择车型",
                    param = new List<string> { "selectorId" },
                    header = new List<Get_Model_InfoResult._props> { new Get_Model_InfoResult._props { key = "description", value = "车型描述" } },
                    content = list.Select(q => new Get_Model_InfoResult._MultiModel._content { description = q.description, selectorId = q.selectorId?.ToString() }).ToList()
                };
                return model;
            }
        }

        protected override List<Get_Model_InfoResult._props> GetVinProps(DbRESTFulRepository repository, dynamic vin)
        {
            //车型，车系，年款，版本，车架号，品牌，品牌代码，变速箱，车身颜色，发动机，发动机类型，排量，生产日期
            var firstVin = vin[0];
            List<Get_Model_InfoResult._props> props = new List<Get_Model_InfoResult._props>();
            props.Add(new Get_Model_InfoResult._props { key = "车型", value = firstVin.name });
            props.Add(new Get_Model_InfoResult._props { key = "车型代码", value = firstVin.code });
            props.Add(new Get_Model_InfoResult._props { key = "生产日期", value = firstVin.productionDate?.ToString() });
            props.Add(new Get_Model_InfoResult._props { key = "分类", value = firstVin.classificationCode });
            props.Add(new Get_Model_InfoResult._props { key = "选择", value = firstVin.opc });
            props.Add(new Get_Model_InfoResult._props { key = "外饰", value = firstVin.exteriorCode });
            props.Add(new Get_Model_InfoResult._props { key = "内饰", value = firstVin.interiorCode });
            props.Add(new Get_Model_InfoResult._props { key = "车架号", value = firstVin.vin });
            return props.Where(q => !string.IsNullOrEmpty(q.value)).ToList();
        }

        protected override List<Get_Model_InfoResult._features> GetVinFeatures(DbRESTFulRepository repository, dynamic vin)
        {
            string featureCodeStr = vin[0].featureCodes;
            if (string.IsNullOrEmpty(featureCodeStr))
            {
                return null;
            }
            var featureCodes = featureCodeStr?.Split(',');
            List<Feature> features = repository.Invoke<Feature>(CSIs.Query_Vin_Features_Standard, new { featureCodes });
            var noDescCodes = featureCodes.Except(features.Select(q => q.featureCode));
            List<Get_Model_InfoResult._features> props = new List<Get_Model_InfoResult._features>();
            props.AddRange(features.Select(q => new Get_Model_InfoResult._features { key = q.featureCode, value = q.featureName }));
            props.AddRange(noDescCodes.Select(q => new Get_Model_InfoResult._features { key = q, value = "" }));
            return props;
        }

        protected override IEnumerable<Query_SubGroupResult> GetSubGroup(DbRESTFulRepository repository, JObject param)
        {
            return repository.Invoke<Query_SubGroupResult>(CSIs.Query_SubGroup_For_Mitsubishi, param);
        }
        protected override List<Query_SubGroupResult> FilterSubGroupsByVin(DbRESTFulRepository repository, List<Query_SubGroupResult> results, JObject param)
        {
            string vin = param.Value<string>(ParamFields._vin);
            if (string.IsNullOrEmpty(vin) || results == null || results.Count == 0)
            {
                return results;
            }
            string selectorId = param.Value<string>(ParamFields._selectorId);
            dynamic vinInfo = null;
            var vins = QueryVinByCode(repository, new Get_Model_InfoParam { vin = vin, selectorId = selectorId });
            try
            {
                vinInfo = vins[0];
            }
            catch
            {
                throw new LogicalException("vin不存在!", 610);
            }
            int? productionDate = vinInfo.productionDate;
            string opc = vinInfo.opc;
            foreach (var subGroup in results)
            {
                if (productionDate.HasValue && subGroup.startTime.HasValue && productionDate < subGroup.startTime)
                {
                    subGroup.belongTo = false;
                    continue;
                }
                if (productionDate.HasValue && subGroup.endTime.HasValue && productionDate > subGroup.endTime)
                {
                    subGroup.belongTo = false;
                    continue;
                }
                if (!string.IsNullOrEmpty(opc) && !string.IsNullOrEmpty(subGroup.applicableModel) && !opc.Equals(subGroup.applicableModel, StringComparison.OrdinalIgnoreCase))
                {
                    subGroup.belongTo = false;
                    continue;
                }
            }
            return results;
        }

        protected override void FilterPartsByVin(DbRESTFulRepository repository, ref List<Query_PartsResult> result, string vin, string selectorId)
        {
            if (string.IsNullOrEmpty(vin))
            {
                return;
            }
            dynamic vinInfo = null;
            var vins = QueryVinByCode(repository, new Get_Model_InfoParam { vin = vin, selectorId = selectorId });
            try
            {
                vinInfo = vins[0];
            }
            catch
            {
                throw new LogicalException("vin不存在!", 610);
            }
            int? productionDate = vinInfo.productionDate;
            string opc = vinInfo.opc;
            string featureCodes = vinInfo.featureCodes;
            List<string> featureList = new List<string>();
            if (!string.IsNullOrEmpty(featureCodes))
            {
                featureList.AddRange(featureCodes.Split(','));
            }
            if (!string.IsNullOrEmpty(opc))
            {
                featureList.Add(opc);
            }
            HashSet<string> featureSet = new HashSet<string>(featureList);
            foreach (var part in result)
            {
                if (productionDate.HasValue && part.startTime.HasValue && productionDate < part.startTime)
                {
                    part.belongToVin = false;
                    continue;
                }
                if (productionDate.HasValue && part.endTime.HasValue && productionDate > part.endTime)
                {
                    part.belongToVin = false;
                    continue;
                }
                if (featureList.Any() && !string.IsNullOrEmpty(part.modelFilter) && !featureList.Contains(part.modelFilter))
                {
                    part.belongToVin = false;
                    continue;
                }
            }
            var groups = result.GroupBy(q => q.imageSN);
            foreach (var list in groups)
            {
                if (list.Any(q => q.belongToVin && !string.IsNullOrEmpty(q.modelFilter)))
                {
                    list.Where(q => string.IsNullOrEmpty(q.modelFilter)).ForEach(x => x.belongToVin = false);
                }
            }
        }
        public override object QueryPartDetail(DbRESTFulRepository repository, JObject param)
        {
            param.RemoveEmptyValues();
            var brandCode = param.Value<string>(ParamFields._brandCode);
            var partId = param.Value<string>(ParamFields._partId);
            var partCode = param.Value<string>(ParamFields._partCode);
            dynamic data = null;

            if (string.IsNullOrEmpty(partId))
            {
                data = repository.Invoke(CSIs.Get_Part_Detail_For_Mitsubishi, new { partCode, brandCode });
            }
            else
            {
                data = repository.Invoke(CSIs.Get_Usage_Detail_For_Mitsubishi, param);
            }
            if (data == null) return null;
            // 1、基本信息赋值
            Query_Part_DetailResult result = JObject.FromObject(data).ToObject<Query_Part_DetailResult>();

            if (result.replacementPartNo != null)
            {
                List<Query_Part_DetailResult._replacement> replacements = repository.Invoke<Query_Part_DetailResult._replacement>(CSIs.Query_Parts_By_Codes, new { partCodes = result.replacementPartNo.Split(',') });
                var replacement = replacements.FirstOrDefault();
                if (replacement != null)
                {
                    replacement.brandCode = brandCode;
                    replacement.brandName = BrandDictionary.GetName(brandCode);
                    result.replacements = new List<Query_Part_DetailResult._replacement>();
                    result.replacements.Add(replacement);
                }
            }

            //4.配件附加属性处理
            var props = new List<Query_Part_DetailResult._prop>
            {
                new Query_Part_DetailResult._prop { key = "件数", value = result.quantity ?? string.Empty },
                new Query_Part_DetailResult._prop { key = "形状", value = data.shape ?? string.Empty },
                new Query_Part_DetailResult._prop { key = "颜色", value = data.color ?? string.Empty },
                new Query_Part_DetailResult._prop { key = "规格", value = data.standard ?? string.Empty },
                new Query_Part_DetailResult._prop { key = "材料", value = data.material ?? string.Empty },
                new Query_Part_DetailResult._prop { key = "大小", value = data.size ?? string.Empty },
                new Query_Part_DetailResult._prop { key = "备注", value = data.remark ?? string.Empty }
            };
            result.props = props.Where(q => !string.IsNullOrEmpty(q.value)).ToList();
            return result;
        }

        protected override dynamic GetModelsByPart(DbRESTFulRepository repository, int pageIndex, int pageSize, string brandCode, string partCode)
        {
            return repository.Invoke(CSIs.Query_Models_By_Part_Standard, new { pageIndex, pageSize, brandCode, partCode });
        }

        protected override List<QuickPartResult> QuickQueryPartsFilterByUsage_Vin(DbRESTFulRepository repository, List<QuickPartResult> parts, int selectorId, string vin)
        {
            List<QuickPartResult> ret = new List<QuickPartResult>();
            if (!string.IsNullOrEmpty(vin) && parts != null && parts.Any())
            {
                List<string> partCodes = parts.Select(e => e.partCode).Distinct().ToList();
                List<Query_PartsResult> partUsages = repository.Invoke<Query_PartsResult>(CSIs.Query_Quick_PartUsage_For_Mitsubishi, new { selectorId, partCodes });
                if (partUsages != null && partUsages.Any())
                {
                    List<string> usedPartCodes = new List<string>();

                    dynamic vinInfo = repository.Invoke(CSIs.Query_Quick_Vin_For_Mitsubishi, new { vin, selectorId });

                    if (vinInfo != null)
                    {
                        int? productionDate = vinInfo.productionDate;
                        string opc = vinInfo.opc;
                        string featureCodes = vinInfo.featureCodes;
                        List<string> featureList = new List<string>();
                        if (!string.IsNullOrEmpty(featureCodes))
                        {
                            featureList.AddRange(featureCodes.Split(','));
                        }
                        if (!string.IsNullOrEmpty(opc))
                        {
                            featureList.Add(opc);
                        }
                        HashSet<string> featureSet = new HashSet<string>(featureList);
                        foreach (var part in partUsages)
                        {
                            if (productionDate.HasValue && part.startTime.HasValue && productionDate < part.startTime)
                            {
                                continue;
                            }
                            if (productionDate.HasValue && part.endTime.HasValue && productionDate > part.endTime)
                            {
                                continue;
                            }
                            if (featureList.Any() && !string.IsNullOrEmpty(part.modelFilter) && !featureList.Contains(part.modelFilter))
                            {
                                continue;
                            }
                            usedPartCodes.Add(part.partCode);
                        }
                    }

                    if (usedPartCodes.Any())
                    {
                        ret = parts.Where(e => usedPartCodes.Contains(e.partCode)).ToList();
                    }
                }
            }
            return ret;
        }
    }
}
